#三方库
from fastapi import APIRouter,Depends,HTTPException,status
from fastapi.security import OAuth2PasswordRequestForm,OAuth2PasswordBearer
from passlib.context import CryptContext
from datetime import datetime, timedelta, timezone
from jwt.exceptions import InvalidTokenError
import jwt
from typing import Annotated
#调用自己模块
from sqlite.db_user import get_user,create_user
from .email_send import verify_code
from model.user_model import User,Token,UserReg,UserDB,UserConfig,LoginResponse,UserResponse,ChatItemResponse,ChatMessageResponse

user = APIRouter()


#——————————————————————————————————————————全局配置—————————————————————————————————————————————
#登录持续天数
ACCESS_TOKEN_EXPIRE_DAYS = 7
#全局密钥
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
#加密算法
ALGORITHM = "HS256"




pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

#密码加密哈希
def get_password_hash(password: str) -> str:
    return pwd_context.hash(password)

#————————————————————————————————————————————————————————————————————————————————————————————


#———————————————————————————————————————用户获取令牌登录————————————————————————————————————————————


#验证用户密码是否与数据库哈希密码匹配
def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

#认证用户存在且账号密码正确
def authenticate_user(user_db, password: str):
    if not verify_password(password, user_db.hashed_password):
        return False
    return user_db

#创建令牌
def create_access_token(data: dict,token_expire: timedelta | None = None):
    to_encode = data.copy()
    if token_expire:
        expire = datetime.now(timezone.utc) + token_expire
    else:
        expire = datetime.now(timezone.utc) + timedelta(days=7)
    to_encode.update({"exp": expire})
    return jwt.encode(payload=to_encode, key=SECRET_KEY, algorithm=ALGORITHM)

#用户登录获取令牌
@user.post('/token')
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -> LoginResponse:
    user_db : User = await get_user(form_data.username)
    if user_db == None:
        return {'error':"None"}
    user = authenticate_user(user_db, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(days=ACCESS_TOKEN_EXPIRE_DAYS)
    access_token = create_access_token(
        data = {"sub":user.username},
        token_expire = access_token_expires
    )
    
    # 使用模型构造返回数据
    token_response = Token(access_token=access_token, token_type="bearer")
    
    # 构造聊天消息列表
    chat_items = []
    for chat in user.chats:
        messages = []
        for msg in chat.messages:
            messages.append(ChatMessageResponse(
                id=msg.id,
                isuser=msg.isuser,
                content=msg.content
            ))
        
        chat_items.append(ChatItemResponse(
            id=chat.id,
            username=user.username,
            title=chat.title,
            createdAt=chat.createdAt,
            chatmessages=messages
        ))
    
    # 构造用户响应
    user_response = UserResponse(
        id=user.id,
        username=user.username,
        email=user.email,
        money=user.money,
        chats=chat_items
    )
    
    # 构造最终响应
    response = LoginResponse(token=token_response, user=user_response)
    
    return response

#————————————————————————————————————————————————————————————————————————————————————————————

#验证token
async def verify_token(token: Annotated[str, Depends(oauth2_scheme)]):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return True
    except InvalidTokenError:
        return False
    
#作为依赖项
async def verify_user(token: Annotated[str, Depends(oauth2_scheme)]):
    if (await verify_token(token)):
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload["sub"]
    else:
        raise HTTPException(status_code=401,detail="invalid token!")
#——————————————————————————————————————测试请求附带token————————————————————————————————————————


@user.post("/verify")
async def read_users_me(
    current_user: Annotated[bool, Depends(verify_token)],
):
    return current_user

#——————————————————————————————————————————————————————————————————————————————————————————————


#——————————————————————————————————————————注册—————————————————————————————————————————————————

@user.post("/register")
async def register(user:UserReg):
    try:
        code = verify_code.get(user.email,None)
        if code !=None:
            if code[1] < datetime.now():
                return {'error':3} #验证码超时
            else:
                if user.code == verify_code.get(f'{user.email}',False)[0]:
                    state = await create_user(UserDB(username=user.username,
                                                email=user.email,
                                                hashed_password=get_password_hash(user.password),
                                                ))
                    
                    if state == '1':
                        return {'error':1}
                    elif state == '2':
                        return {'error':2}
                    return True
                else:
                    return False
        else:
            return {'error':4}
    except Exception as e:
        return {"error": e}

#——————————————————————————————————————————————————————————————————————————————————————————————